/**
 * 自定义apply实现
 * @param context   上下文this对象
 * @param args      动态参数
 */
Function.prototype.myApply = function(context, args) {
  // 判断调用的对象是否是函数 context是this的指向，this是调用call的函数
  if (typeof this !== 'function') {
    throw new TypeError('Error');
  }
  // 其实也可以用到arguments 这样就不用写形参args
  // 判断context,如果为null 或者dundefined 则等于window
  // context = (typeof context === 'object' ? context : window);
  context = context || window;
  // 防止覆盖掉原有属性
  const key = Symbol();
  // 将调用的函数作为对象的临时方法，要用中括号起来
  // 如果这么写context.key 是将key作为属性放在对象中。
  context[key] = this;
  // 调用这个对象中的函数，，此时的函数的this 指向这个对象
  let result;
  if (!args) {
     result = context[key]();
  } else {
     result = context[key](...args);
  }
  // 将Symbol属性删除
  delete context[key];
  // 返回函数的结果
  return result;
};

// 测试一下
var value = 2;

var obj = {
  value: 1,
  key: function() {
    console.log('wzy');
  }
}

function bar(name, age) {
  console.log(this.value);
  return {
    value: this.value,
    name: name,
    age: age
  }
}
// 浏览器中指向window
console.log('myApply:');
console.log(bar.myApply(null));// 2
console.log(bar.myApply(obj, ['kevin', 18]));
console.log(obj);

console.log('apply:');
console.log(bar.apply(null));// 2
console.log(bar.apply(obj, ['kevin', 18]));